home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Tele
/
C
/
Comet2.1.3.cpt
/
Comet
/
serial.c
< prev
next >
Wrap
Text File
|
1991-10-30
|
14KB
|
700 lines
/*
Copyright Cornell University 1986. All rights are reserved.
*/
#include <em.h>
#include <serial.h>
#include <3270.h>
#include <h19.h>
#include <errors.h>
#include <config.h>
#include <menudefs.h>
#include <osutil.h>
/* defines for serial port xon/xoff */
#define SHUTOFF 1600
#define SERBUFSIZE 4096
/* modemport menu items in serial version */
#define MODEMPORT 1
#define PRINTERPORT 2
#define NUMPORTS 2
int fdcapture = -1; /* fd for transfer file */
char * aserinbuf; /* input buffer to assign to Modem port */
char * bserinbuf; /* ditto for printer port */
char * readbuf; /* our read buffer */
/* buffers for serial reads */
char xoffmess[] = "No XON/XOFF--Capture may lose text";
int noserd; /* SERD serial driver resource not present */
struct winds * modembusy; /* port in use flag */
struct winds * printerbusy;
short modemopened; /* port was opened flag */
short printopened;
#define baud38400 1
int baudrates[] = {baud57600, baud38400, baud19200, baud9600, baud4800, baud2400, baud1200, baud300};
int dataconst[] = {data8, data7, data6};
/* 5, 6, 7, 8 data bits */
int parityconst[] = {noParity, evenParity, oddParity};
/* none, even, odd */
int stopconst[] = {stop20, stop15, stop10};
/* 1, 1.5, 2 stop bits */
extern Handle menu[];
/* check the serial port for fresh data
uses emdp by default
*/
serial_service()
{
long readcnt;
long sercnt;
if (!emdp->connopen)
return;
SerGetBuf(emdp->refin, &sercnt);
if (noserd) {
/* if the SERD is not present we must do xon/xoff handling */
if (emdp->xon) {
if (sercnt > SHUTOFF) {
/* turn it off */
serputchar(X_OFF);
emdp->xon = FALSE;
}
}
else if (sercnt < SHUTOFF) {
/* turn transmission back on */
serputchar(X_ON);
emdp->xon = TRUE;
}
}
if (sercnt) {
register char * readp;
register char * bufend;
if (emdp->icon_up)
emalert(); /* highlight icon to show activity */
if (sercnt > SERBUFSIZE) {
readcnt = SERBUFSIZE;
}
else {
readcnt = sercnt;
}
FSRead(emdp->refin, &readcnt, readbuf);
#ifdef USESERIALWAIT
if (autokey || readcnt <= 1)
serialwait = 0;
else
serialwait = 0;
/* wait for i ticks to service serial again */
#endif
emdp->in_cnt += readcnt;
if ( emdp->in_cnt >= 1000 ) {
/* turn the kilochar counter over */
emdp->in_cnt = 0;
emdp->kin_cnt++;
drawincount();
}
for (readp = readbuf, bufend = readp + readcnt; readp < bufend; readp++) {
/* mash the high bit down for the emulator */
*readp &= 0x7f;
}
(*emdp->emstr)(readbuf, (unsigned short) readcnt);
if (readcnt <= 3 || autokey || autokeypersist) {
/* if the user is holding a key down, make sure the cursor shows */
setcursor();
if (autokey && autokeywait != NULL) {
autokeypersist = TRUE;
tm_tset(60, clrautokeywait, NULL, autokeywait);
}
}
emdp->hycnewdata = TRUE;
#ifdef SERFILECAPTURE
/* an old feature we will probably support at a higher level */
if (fdcapture >= 0) {
char * stake;
for (stake = readp = readbuf; readp < bufend; readp++) {
if (*readp == LF) {
write(fdcapture, stake, readp - stake);
/* skip the LF */
stake = readp + 1;
}
}
if (readp > stake)
/* write out what's left */
write(fdcapture, stake, readp - stake);
}
#endif
}
}
char seropenerr[] = "Not enough memory to open Serial Driver";
openserport()
{
OSErr result;
char leaveDTRup;
struct winds * thedp;
thedp = emdp;
if (readbuf == NULL) {
readbuf = malloc(SERBUFSIZE);
if (readbuf == NULL) {
return(-1);
}
}
if (emdp->refin)
/* don't open twice */
return(0);
if (emdp->usebport) {
/* use the Printer Port */
if (printerbusy) {
if (queryserclose(printerbusy)) {
closeconn(printerbusy);
getcontext(thedp); /* restore our context */
}
else
return(-1);
}
if (bserinbuf == NULL) {
bserinbuf = malloc(SERBUFSIZE);
if (bserinbuf == NULL) {
error(&seropenerr[0]);
return(-1);
}
}
emdp->refin = -8;
emdp->refout = -9;
}
else {
/* use the Modem Port */
if (modembusy) {
if (queryserclose(modembusy)) {
closeconn(modembusy);
getcontext(thedp); /* restore our context */
}
else
return(-1);
}
#ifdef OMNITEST
if (omni_test()) {
/* verify that the Omninet driver is not mucking around with the port */
porterr(0);
return(-1);
}
#endif
if (aserinbuf == NULL) {
aserinbuf = malloc(SERBUFSIZE);
if (aserinbuf == NULL) {
error(&seropenerr[0]);
return(-1);
}
}
emdp->refin = -6;
emdp->refout = -7;
}
if ((result = RAMSDOpen(emdp->usebport ? sPortB : sPortA)) != noErr ) {
/* open failed */
if (result == openErr) {
noserd = TRUE;
error("No SERD resource available; using manual XON/XOFF");
if ((result = OpenDriver(emdp->usebport ? "\P.BOut" : "\P.AOut", &emdp->refout) ) ) {
porterr(result);
return(-1);
}
}
else {
/* (result == portInUse || result == portNotCf) don't cover all bases! */
porterr(result);
return(-1);
}
}
else {
/* make the SERD do XON/XOFF */
SerShk serShk;
noserd = FALSE;
if (emdp->baud > baud38400) {
/* use XON/XOFF at speeds < 38,400 baud */
serShk.fXOn = (Byte) TRUE; /* output XON-XOFF on/off */
serShk.fCTS = (Byte) FALSE; /* CTS output off */
serShk.xOn = (char) CTLQ; /* xon char DC1 */
serShk.xOff = (char) CTLS; /* xoff char DC3 */
serShk.errs = (Byte) 0; /* input abort settings ALL = 0160 */
serShk.evts = (Byte) 0; /* status junk */
serShk.fInX = (Byte) TRUE; /* input XON-XOFF on/off */
serShk.null = (Byte) FALSE; /* CTS input off */
if (Control(emdp->refout, _newrom() ? 14 : 10, &serShk))
error(xoffmess);
/* "Advanced" control call, dups SerHShake adding DTR input as 8th byte,
used when not old ROM */
}
/* make control call so Mac + will leave its DTR line asserted when you close driver */
if (_newrom()) {
leaveDTRup = 0x80; /* mash bit 7 down for DTR */
Control(emdp->refout, 16, &leaveDTRup);
}
}
SerSetBuf(emdp->refin, emdp->usebport ? bserinbuf : aserinbuf, SERBUFSIZE);
if (emdp->usebport) {
printerbusy = emdp;
printopened = TRUE;
}
else {
modembusy = emdp;
modemopened = TRUE;
}
sermenuset();
if (setupport())
return(-1);
emdp->xon = TRUE;
emdp->ucb.u_sendm = EVERYC; /* asciitoken--send promptly */
tickserial = cticks + 2;
if (tickserial == 0)
tickserial++;
/* start up tick counter for service */
return(0);
}
setupport()
{
int serconf;
if (!emdp->refin)
return(-1);
serconf = 0;
serconf = emdp->baud
| emdp->parity
| emdp->stop
| emdp->data;
if (SerReset(emdp->refout, serconf) || SerReset(emdp->refin, serconf)) {
error("Can't configure serial port");
return(-1);
}
return(0);
}
localconfig()
{
Handle hconfig;
struct serconfig * confp;
if ((hconfig = Get1Resource('CONF', SERCONFID)) == (Handle) NULL) {
/* no configuration resource exists */
emdp->usebport = NOPORT;
emdp->baud = baud9600;
emdp->parity = noParity;
emdp->stop = stop20;
emdp->data = data8;
emdp->data = data8;
/* wait until user desires to open driver */
}
else {
confp = (struct config *) *hconfig;
emdp->usebport = confp->cport;
emdp->baud = confp->cbaud;
emdp->parity = confp->cparity;
emdp->stop = confp->cstop;
emdp->data = confp->cdata;
ReleaseResource(hconfig);
}
}
setlocalconfig()
{
struct serconfig * confp;
Handle hconfig;
if ((hconfig = Get1Resource('CONF', SERCONFID)) != NULL) {
/* kill current version */
RmveResource(hconfig);
UpdateResFile(emdp->resfid);
DisposHandle(hconfig);
}
/* add new resource */
hconfig = NewHandle((Size) sizeof(struct serconfig));
if (hconfig == NULL) {
error("Out of memory");
return(-1);
}
AddResource(hconfig, 'CONF', SERCONFID, "\P");
if (ResError()) {
error("Can't create CONF 1 resource");
return(-1);
}
/* set it */
HLock(hconfig);
confp = (struct config *) *hconfig;
confp->cport = emdp->usebport;
confp->cbaud = emdp->baud;
confp->cparity = emdp->parity;
confp->cstop = emdp->stop;
confp->cdata = emdp->data;
HUnlock(hconfig);
ChangedResource(hconfig);
UpdateResFile(emdp->resfid);
if (ResError()) {
error("No serial configuration update");
return(-1);
}
ReleaseResource(hconfig);
}
porterr(code)
int code;
{
emdp->refin = emdp->refout = 0;
if (emdp->usebport)
error("The Printer Port can't be used--is AppleTalk off?");
else
error("The Modem Port can't be used");
}
closeserport(twp)
struct winds * twp;
{
if (!twp->refin)
return;
if (twp->autohangup)
Control(twp->refout, 18, (Ptr) NULL);
if (twp->usebport) {
if (!noserd)
RAMSDClose(sPortB);
else {
CloseDriver(twp->refout);
}
printerbusy = NULL;
}
else {
if (!noserd)
RAMSDClose(sPortA);
else {
CloseDriver(twp->refout);
}
modembusy = NULL;
}
twp->refin = twp->refout = 0;
}
omni_test()
{
int refnum;
if (!OpenDriver("\P.OmniDriver", &refnum)) {
CloseDriver(refnum);
return(TRUE);
}
else
return(FALSE);
}
/* put out a character */
serputchar(thechar)
char thechar;
{
long count = 1;
if (!emdp->refout)
return(-1);
serialwait = 0;
FSWrite(emdp->refout, &count, &thechar);
++emdp->out_cnt;
return(0);
}
/* update the counter, nothing else needed */
serputflush()
{
drawoutcount();
}
sersendstr(strp)
char * strp;
{
long count;
serialwait = 0;
count = strlen(strp);
FSWrite(emdp->refout, &count, strp);
emdp->out_cnt += count;
drawoutcount();
}
/* send a block */
sersendcount(strp, strcount)
char * strp;
short strcount;
{
long count = strcount;
serialwait = 0;
FSWrite(emdp->refout, &count, strp);
emdp->out_cnt += count;
drawoutcount();
}
sersendBreak()
{
long ticks;
SerSetBrk(emdp->refout);
Delay((long) 30, &ticks);
SerClrBrk(emdp->refout);
}
/* routines follow to handle menus that control the serial port */
menuserial(theItem)
short theItem;
{
/* reset data, parity, and stop bit settings */
if (theItem == SERPORTRESET) {
SysPtr sysparam;
sysparam = GetSysPPtr();
if (emdp->usebport)
sysparam->valid &= 0xFFFFFFF0; /* blank out Printer Port configuration */
else
sysparam->valid &= 0xFFFFFF0F; /* blank out Modem Port configuration */
if (WriteParam()) /* save the reset configuration */
error("Couldn't update parameter RAM");
return(TRUE);
}
else if (theItem == SERPORTHANGUP) {
serhangup(keydp);
return(TRUE);
}
else if (theItem == SERAUTOHANG) {
keydp->autohangup = !keydp->autohangup;
keydp->confchanged = TRUE;
CheckItem(menu[SERIALMENU], SERAUTOHANG, keydp->autohangup ? (Boolean) TRUE : (Boolean) FALSE);
return(TRUE);
}
getcontext(keydp);
switch (theItem) {
case SERSENDHIER: {
/* should be hierarchical, for now is sytek escape */
(*emdp->putchar)(CTLA);
(*emdp->putchar)(CTLB);
return(TRUE);
}
case BAUD57600:
case BAUD38400:
case BAUD19200:
case BAUD9600:
case BAUD4800:
case BAUD2400:
case BAUD1200:
case BAUD300:
{
emdp->baud = baudrates[theItem - BAUD57600];
break;
}
case DATA6: {
emdp->data = data6;
break;
}
case DATA7: {
emdp->data = data7;
break;
}
case DATA8: {
emdp->data = data8;
break;
}
case PARITYNONE: {
emdp->parity = noParity;
break;
}
case PARITYEVEN: {
emdp->parity = evenParity;
break;
}
case PARITYODD: {
emdp->parity = oddParity;
break;
}
case STOP1: {
emdp->stop = stop10;
break;
}
case STOP1HALF: {
emdp->stop = stop15;
break;
}
case STOP2: {
emdp->stop = stop20;
break;
}
default: {
return(TRUE);
}
}
keydp->confchanged = TRUE;
sermenuset();
setupport();
return(FALSE);
}
sermenuset()
{
int count;
CheckItem(menu[SERIALMENU], SERAUTOHANG, emdp->autohangup ? (Boolean) TRUE : (Boolean) FALSE);
/* blank exclusive items out */
for (count = BAUD57600; count <= STOP1; count++) {
CheckItem(menu[SERIALMENU], count, FALSE);
}
/* check baud rate */
for (count = 0; count < NUMBAUDS; count++) {
if (baudrates[count] == emdp->baud) {
CheckItem(menu[SERIALMENU], count + BAUD57600, TRUE);
}
}
/* check data bits */
for (count = 0; count < DATAITEMS; count++) {
if (dataconst[count] == emdp->data) {
CheckItem(menu[SERIALMENU], count + DATA8, TRUE);
break;
}
}
/* check parity bits */
for (count = 0; count < PARITYITEMS; count++) {
if (parityconst[count] == emdp->parity) {
CheckItem(menu[SERIALMENU], count + PARITYNONE, TRUE);
break;
}
}
/* check stop bits */
for (count = 0; count < STOPITEMS; count++) {
if (stopconst[count] == emdp->stop) {
CheckItem(menu[SERIALMENU], count + STOP2, TRUE);
break;
}
}
}
/* hang up the phone line(s); close will cause DTR to drop */
sercleanup()
{
short refnum;
if (noserd) {
if (modemopened) {
OpenDriver("\P.AOut", &refnum);
CloseDriver(refnum);
}
if (printopened) {
OpenDriver("\P.BOut", &refnum);
CloseDriver(refnum);
}
}
else {
if (modemopened) {
RAMSDOpen(sPortA);
RAMSDClose(sPortA);
}
if (printopened) {
RAMSDOpen(sPortA);
RAMSDClose(sPortB);
}
}
}
/* hangup the phone line by dropping DTR */
serhangup(twp)
struct winds * twp;
{
if (twp->refout) {
Control(twp->refout, 18, (Ptr) NULL);
}
else {
/* driver is closed, reopen & THEN hang it up */
getcontext(twp);
openserport();
Control(twp->refout, 18, (Ptr) NULL);
closeserport(twp);
}
}